#include "ibusadapter.h"

#include <QDBusConnection>
#include <QDBusError>
#include <QKeyEvent>
#include <QDebug>

IBusAdapter::IBusAdapter(InputContext* inputCtx, QObject* parent)
    : QObject(parent)
    , m_inputCtx(inputCtx)
    , m_ibusBusInterface(nullptr)
    , m_ibusEngineInterface(nullptr)
    , m_isFocused(false)
{
    // 关联InputContext信号
    connect(m_inputCtx, &InputContext::candidatesUpdated, this, &IBusAdapter::onCandidatesUpdated);
    connect(m_inputCtx, &InputContext::stateChanged, this, &IBusAdapter::onInputStateChanged);
    // 关联自身信号到InputContext
    connect(this, &IBusAdapter::ibusKeyEvent, this, [this](int keyVal, int keyCode, Qt::KeyboardModifiers modifiers, bool isPressed) {
        if (!m_isFocused) return;
        // 转换为Qt KeyEvent并转发
        Qt::Key key = static_cast<Qt::Key>(keyVal);
        QString text = QKeySequence(key).toString();
        QKeyEvent* event = new QKeyEvent(isPressed ? QEvent::KeyPress : QEvent::KeyRelease, key, modifiers, text);
        m_inputCtx->handleKeyEvent(event);
        delete event;
    });
}

IBusAdapter::~IBusAdapter() {
    if (m_ibusBusInterface) delete m_ibusBusInterface;
    if (m_ibusEngineInterface) delete m_ibusEngineInterface;
}

// 连接IBus服务（DBus总线）
bool IBusAdapter::connectToIBus() {
    // 连接到系统DBus（IBus默认使用session bus）
    QDBusConnection bus = QDBusConnection::sessionBus();
    if (!bus.isConnected()) {
        qWarning() << "[IBus] DBus连接失败：" << bus.lastError().message();
        return false;
    }

    // 创建IBus总线接口（服务：org.freedesktop.IBus，路径：/org/freedesktop/IBus，接口：org.freedesktop.IBus）
    m_ibusBusInterface = new QDBusInterface(
        "org.freedesktop.IBus",
        "/org/freedesktop/IBus",
        "org.freedesktop.IBus",
        bus,
        this
    );

    if (!m_ibusBusInterface->isValid()) {
        qWarning() << "[IBus] 总线接口无效：" << m_ibusBusInterface->lastError().message();
        return false;
    }

    qInfo() << "[IBus] 连接DBus成功";
    return true;
}

// 注册为IBus引擎
bool IBusAdapter::registerEngine(const QString& engineName) {
    if (!m_ibusBusInterface) {
        qWarning() << "[IBus] 未连接DBus，无法注册引擎";
        return false;
    }

    // 1. 请求创建引擎对象（IBus方法：CreateEngine）
    QDBusReply<QDBusObjectPath> createReply = m_ibusBusInterface->call("CreateEngine", engineName);
    if (!createReply.isValid()) {
        qWarning() << "[IBus] 创建引擎失败：" << createReply.error().message();
        return false;
    }

    // 2. 保存引擎对象路径（如/org/freedesktop/IBus/Engine/1234）
    m_enginePath = createReply.value().path();
    qInfo() << "[IBus] 引擎创建成功，路径：" << m_enginePath;

    // 3. 创建引擎接口（用于后续交互）
    m_ibusEngineInterface = new QDBusInterface(
        "org.freedesktop.IBus",
        m_enginePath,
        "org.freedesktop.IBus.Engine",
        QDBusConnection::sessionBus(),
        this
    );

    if (!m_ibusEngineInterface->isValid()) {
        qWarning() << "[IBus] 引擎接口无效：" << m_ibusEngineInterface->lastError().message();
        return false;
    }

    // 4. 导出自身DBus接口（供IBus调用ProcessKeyEvent等方法）
    QDBusConnection::sessionBus().registerObject(m_enginePath, this, QDBusConnection::ExportAllSlots);
    return true;
}

// 接收InputContext的候选词，同步到IBus
void IBusAdapter::onCandidatesUpdated(const QVector<PinyinCandidate>& candidates) {
    if (!m_ibusEngineInterface || !m_isFocused) return;

    // 转换为IBus候选词格式
    m_ibusCandidates.clear();
    for (const auto& cand : candidates) {
        m_ibusCandidates.append({ cand.text, cand.pinyin });  // 注释用拼音
    }

    // 发送候选词到IBus
    sendCandidatesToIBus(m_ibusCandidates);
    qDebug() << "[IBus] 同步候选词：" << m_ibusCandidates.size() << "个";
}

// 接收InputContext的状态变更
void IBusAdapter::onInputStateChanged(const InputState& state) {
    if (!m_ibusEngineInterface) return;

    // 同步输入文本（正在输入的拼音/已确认的汉字）
    if (!state.compositionText.isEmpty()) {
        sendTextToIBus(state.compositionText, true);  // 正在输入的文本（composition）
    } else if (!state.committedText.isEmpty()) {
        sendTextToIBus(state.committedText, false);  // 已确认的文本（commit）
    }
}

// IBus DBus接口：处理键盘事件（IBus调用此方法传递按键）
void IBusAdapter::ProcessKeyEvent(int keyVal, int keyCode, uint modifiers, bool isPressed, uint timestamp) {
    Q_UNUSED(keyCode);
    Q_UNUSED(timestamp);

    // 转换IBus修饰符为Qt修饰符
    Qt::KeyboardModifiers qtModifiers = Qt::NoModifier;
    if (modifiers & 0x0001) qtModifiers |= Qt::ShiftModifier;    // IBus_SHIFT_MASK
    if (modifiers & 0x0004) qtModifiers |= Qt::ControlModifier;  // IBus_CONTROL_MASK
    if (modifiers & 0x0008) qtModifiers |= Qt::AltModifier;      // IBus_MOD1_MASK

    // 转发事件到InputContext
    emit ibusKeyEvent(keyVal, keyCode, qtModifiers, isPressed);
}

// IBus DBus接口：设置引擎能力（如是否支持候选词）
void IBusAdapter::SetCapabilities(uint capabilities) {
    Q_UNUSED(capabilities);
    qInfo() << "[IBus] 设置能力：" << capabilities;
}

// IBus DBus接口：获取输入焦点
void IBusAdapter::FocusIn() {
    m_isFocused = true;
    qInfo() << "[IBus] 获得输入焦点";
}

// IBus DBus接口：失去输入焦点
void IBusAdapter::FocusOut() {
    m_isFocused = false;
    m_ibusCandidates.clear();
    sendCandidatesToIBus(m_ibusCandidates);  // 清空候选词
    qInfo() << "[IBus] 失去输入焦点";
}

// IBus DBus接口：重置引擎
void IBusAdapter::Reset() {
    m_inputCtx->cancelInput();  // 调用InputContext重置输入
    qInfo() << "[IBus] 引擎重置";
}

// 发送候选词到IBus
void IBusAdapter::sendCandidatesToIBus(const QVector<IBusCandidate>& candidates) {
    // IBus要求候选词参数为QVariantList，每个元素是QVariantMap（含"text"和"comment"）
    QVariantList candidateList;
    for (const auto& cand : candidates) {
        QVariantMap candMap;
        candMap["text"] = cand.text;
        candMap["comment"] = cand.comment;
        candidateList.append(candMap);
    }

    // 调用IBus引擎的SetCandidates方法
    QDBusReply<void> reply = m_ibusEngineInterface->call("SetCandidates", candidateList);
    if (!reply.isValid()) {
        qWarning() << "[IBus] 发送候选词失败：" << reply.error().message();
    }
}

// 发送文本到IBus
void IBusAdapter::sendTextToIBus(const QString& text, bool isComposition) {
    if (text.isEmpty()) return;

    if (isComposition) {
        // 发送正在输入的文本（如拼音）：调用SetCompositionText
        QVariantMap compMap;
        compMap["text"] = text;
        compMap["cursor_pos"] = text.size();  // 光标在末尾
        QDBusReply<void> reply = m_ibusEngineInterface->call("SetCompositionText", compMap);
        if (!reply.isValid()) {
            qWarning() << "[IBus] 发送Composition文本失败：" << reply.error().message();
        }
    } else {
        // 发送已确认的文本（如汉字）：调用CommitText
        QVariantMap commitMap;
        commitMap["text"] = text;
        QDBusReply<void> reply = m_ibusEngineInterface->call("CommitText", commitMap);
        if (!reply.isValid()) {
            qWarning() << "[IBus] 发送Commit文本失败：" << reply.error().message();
        }
    }
}